# This program correlates an Xbar32 slot file and an
# xbar32 map file and creates a list similar to a wirelist
# For usage type "perl mapslot32 -h"

use Getopt::Std;

use strict;

# Globals
my %Hosts = ();
my %Xbars = ();
my %Slots = ();


# read in the map file
sub read_map {

	my $host;
	my $xbar_name;

	while (<M>) {
	
		if (/^$/) {
			$host = "";
			$xbar_name = "";
	
		} elsif (/^h - (h[0-9]+)$/) {
			$host = $1;
	
		} elsif ($host && /[01] s - (x\d+) (\d+)$/) {
			$Hosts{$host}->{XB} = $1;
			$Hosts{$host}->{XB_PORT} = $2;
	
		} elsif ($host && /^address (.*)$/) {
			$Hosts{$host}->{MAC} = $1;
	
		} elsif (/^s - (x\d+)$/) {
			$xbar_name = $1;
		
		} elsif ($xbar_name && /^(\d+)$/) {
			$Xbars{$xbar_name}->{NPORTS} = $1;
	
		} elsif ($xbar_name && /^(\d+) ([sh]) - (x\d+) (\d+)$/) {
			$Xbars{$xbar_name}->{PORT}[$1]{CONN_TYPE} = $2;	
			$Xbars{$xbar_name}->{PORT}[$1]{TO} = $3;	
			$Xbars{$xbar_name}->{PORT}[$1]{TO_PORT} = $4;	
	
		} elsif ($xbar_name && /^ID (\d+)$/) {
			$Xbars{$xbar_name}->{ID} = $1;
	
		} elsif ($xbar_name && /^decodeID (\d+):(\d+)$/) {
			$Xbars{$xbar_name}->{BRD_ID} = $1;
			$Xbars{$xbar_name}->{XB_ON_BRD} = $2;
		}
	}
}


sub read_slots {
	my $line = 1;
	while (<S>) {
		(/(^\w+)\s+slot\s+(\d+)\s+(\d+)/) || die("funkyness on line $line of $::opt_s");
		$Slots{$1}{$3} = $2;
		$line++;
	}
}


sub dumpXbars {
	my $this_xb;

	printf("dumping xbars\n");

	foreach my $xb (sort keys %Xbars) {
		$this_xb = $Xbars{$xb};
		printf("$xb ID: %d decodeId: %d, xbonbrd:%d\n",
					$this_xb->{ID},
					$this_xb->{BRD_ID},
					$this_xb->{XB_ON_BRD});
		for (my $i = 0; $i < $this_xb->{NPORTS}; $i++) {
			printf("\tport $i %s - %s %s %s\n", 
				$this_xb->{PORT}[$i]{CONN_TYPE},
				$this_xb->{PORT}[$i]{TO},
				$this_xb->{PORT}[$i]{TO_PORT});
		}
	}
}

sub dumpHosts {
	printf("dumping hosts\n");
	foreach my $host (keys %Hosts) {
		printf("host: $host, xb: %s, port: %d, mac: %s\n",
					$Hosts{$host}->{XB},
					$Hosts{$host}->{XB_PORT},
					$Hosts{$host}->{MAC});
	}
}


sub main {
	my $this_xb;	
	my $xb_clos_slot;	
	my $xb_brd_id;
	my $host_xb_name;	
	my $host_xb_id;	
	my %cmap;
	my %xb_id;
  my $xb_port;

	getopt("s:m:");

	($::opt_s && $::opt_m) || die "Usage: $0 -m <mapfile> -s <slotfile>";

	open(M, "<$::opt_m") || die("couldn't open map file");
	open(S, "<$::opt_s") || die("couldn't open slot file");


	read_map();
	read_slots();

	# make a hash by xbar ID pointing to it's clos and slot
	foreach my $xb (keys %Xbars) {

		$this_xb = $Xbars{$xb};
		$xb_brd_id = $this_xb->{BRD_ID};

		undef $xb_clos_slot;

		foreach my $clos (keys %Slots) {
			$xb_clos_slot = $Slots{$clos}{$xb_brd_id};
			if ($Slots{$clos}{$xb_brd_id}) {
				$xb_id{$this_xb->{BRD_ID}}{CLOS} = $clos;
				$xb_id{$this_xb->{BRD_ID}}{SLOT} = $xb_clos_slot;
				last;
			}
		}
		(defined $xb_clos_slot) ||
				die("For xbar $xb couldn't find brd id $xb_brd_id in $::opt_s file!")
	}


	# now look up the clos/slot foreach host and build another hash
  # by clos, then slot then port.
	foreach my $h (keys %Hosts) {
		$host_xb_name = $Hosts{$h}->{XB};
		$host_xb_id = $Xbars{$host_xb_name}->{BRD_ID};
		$cmap{$xb_id{$host_xb_id}{CLOS}}{$xb_id{$host_xb_id}{SLOT}}{$Hosts{$h}{XB_PORT}} = $Hosts{$h}{MAC}
	}

  # Print out clos/slot/port/mac mappings. Assume XB 32's.
  foreach my $clos (sort keys %cmap) {
    foreach my $slot (sort { $a <=> $b } keys %{$cmap{$clos}}) {
      for (my $port = 16; $port < 32; $port++) {
        if (defined $cmap{$clos}{$slot}{$port}) {
  	       printf("$clos slot $slot port $port %s\n", $cmap{$clos}{$slot}{$port});
        } else {
  	       print("$clos slot $slot port $port <never>\n");
        }
      }
    }
  }

	return 1;
}


&main

